#pragma once
#include <stdlib.h>
#include <stdio.h>

namespace DirectUI
{
	namespace UICollections
	{
		interface __declspec(uuid("{B265A6F8-77A4-43D9-B5BD-D84D48B4D96C}")) IUIIterator : public IUIObject
		{
			virtual bool			MoveNext() = 0;
			virtual	IUIObject*		Current() = 0;
		};

		interface __declspec(uuid("{FE58D873-8C81-4836-B5F6-FBFC3890745F}")) IUIVector : IUIObject
		{
			virtual void			Append(IUIObject* value) = 0;
			virtual void			Clear() = 0;
			virtual IUIObject*		GetAt(unsigned int index) = 0;
			virtual void			InsertAt(unsigned int index, IUIObject* lpValue) = 0;
			virtual void			SetAt(unsigned int index, IUIObject* lpValue) = 0;
			virtual void			RemoveAt(unsigned int index) = 0;
			virtual unsigned int	Size() = 0;
			virtual	bool			GetIterator(unsigned int index, IUIIterator** lppIterator) = 0;

		};

		interface __declspec(uuid("{DF34B3D8-5CB7-44F8-B015-E8E5BA9E15BF}")) IUIMap : IUIObject
		{
			virtual void			Clear() = 0;
			virtual bool			HasKey(IUIObject* lpKeyObject) = 0;	
			virtual bool			Insert(IUIObject* lpKeyObject, IUIObject* lpValueObject) = 0;
			virtual	IUIObject*		Lookup(IUIObject* lpKeyObject) = 0;
			virtual	void			Remove(IUIObject* lpKeyObject) = 0;
			virtual	bool			GetBeginIterator(IUIIterator** lppIterator) = 0;
		};

		struct CUIObjectLess : public std::binary_function<CUIObjectPtr<IUIObject>, CUIObjectPtr<IUIObject>, bool>
		{
			bool operator()(const CUIObjectPtr<IUIObject>& _Left, const CUIObjectPtr<IUIObject>& _Right) const
			{
				return _Left->IsLess(_Right);
			}
		};

		class CUIVector : public CUINoAggregateObjectImplHelper<IUIVector, CUIVector, IUIVector>
		{
			DECLARE_CLASS(CUIVector, vector)
		public:
			class CUIVectorIterator : public CUINoAggregateObjectImplHelper<IUIIterator, CUIVectorIterator, IUIIterator>
			{
				DECLARE_CLASS(CUIVectorIterator, VectorIterator)
				friend class CUIVector;
			public:
				virtual bool MoveNext() 
				{
					CUIVector* pVector = (CUIVector*)(IUIVector*)m_spVector;
					if ( m_iterator == pVector->m_vector.end() )
						return false;
					++m_iterator;
					return true;
				}
				virtual	IUIObject* Current()
				{
					return *m_iterator;
				}
			private:
				std::vector<CUIObjectPtr<IUIObject>>::iterator m_iterator;
				CUIObjectPtr<IUIVector>	m_spVector;
			};
		public:
			CUIVector()
			{

			}
			~CUIVector()
			{

			}

			virtual void		Append(IUIObject* value) { m_vector.push_back(value); }
			virtual void		Clear() { m_vector.clear(); }
			virtual IUIObject*	GetAt(unsigned int index)
			{
				if ( index >= 0 && index < m_vector.size() )
					return m_vector[index];
				return NULL;
			}
			virtual void		InsertAt(unsigned int index, IUIObject* lpValue)
			{
				if ( index >= 0 && index < m_vector.size() )
					m_vector.insert(m_vector.begin()+index, lpValue);
			}
			virtual void		SetAt(unsigned int index, IUIObject* lpValue)
			{
				if ( index >= 0 && index < m_vector.size() )
					m_vector[index] = lpValue;
			}
			virtual void		RemoveAt(unsigned int index)
			{
				if ( index >= 0 && index < m_vector.size() )
					m_vector.erase(m_vector.begin()+index);
			}
			virtual unsigned int Size()
			{
				return m_vector.size();
			}
			virtual	bool GetIterator(unsigned int index, IUIIterator** lppIterator)
			{
				if ( !lppIterator )
					return false;
				*lppIterator = NULL;
				if ( index >= 0 && index < m_vector.size() )
				{
					CUIVectorIterator* p = new CUIVectorIterator();
					if ( p )
					{
						p->m_iterator = m_vector.begin()+index;
						p->AddRef();
						p->m_spVector = this;
						*lppIterator = p;
					}
					return true;
				}
				return false;
			}
		private:
			std::vector<CUIObjectPtr<IUIObject>>	m_vector;
		};

		class CUIMap : public CUINoAggregateObjectImplHelper<IUIMap, CUIMap, IUIMap>
		{
			DECLARE_CLASS(CUIMap, map)
		public:
			class CUIMapIterator : public CUINoAggregateObjectImplHelper<IUIIterator, CUIMapIterator, IUIIterator>
			{
				DECLARE_CLASS(CUIMapIterator, MapIterator)
				friend class CUIMap;
			public:
				virtual bool MoveNext() 
				{
					assert(false);
					/*CUIMap* pMap = (CUIMap*)(IUIMap*)m_spMap;
					if ( m_iterator == pMap->m_map.end() )
						return false;
					++m_iterator;*/
					return true;
				}
				virtual	IUIObject* Current()
				{
					return m_iterator->second;
				}
			private:
				std::map<CUIObjectPtr<IUIObject>, CUIObjectPtr<IUIObject>>::iterator m_iterator;
				CUIObjectPtr<IUIMap>	m_spMap;
			};

			virtual void Clear() { m_map.clear(); }
			virtual bool HasKey( IUIObject* lpKeyObject ) { return Lookup(lpKeyObject) != NULL; }
			virtual bool Insert( IUIObject* lpKeyObject, IUIObject* lpValueObject ) { m_map[lpKeyObject] = lpValueObject; return true; }
			virtual IUIObject* Lookup( IUIObject* lpKeyObject )
			{
				CUIObjectPtr<IUIObject> spValue = lpKeyObject;
				std::map<CUIObjectPtr<IUIObject>, CUIObjectPtr<IUIObject>, CUIObjectLess>::iterator pit = m_map.find(spValue);
				if ( pit != m_map.end() )
					return pit->second;
				return NULL;
			}
			virtual void Remove( IUIObject* lpKeyObject ) 
			{ 
				CUIObjectPtr<IUIObject> spValue = lpKeyObject;
				std::map<CUIObjectPtr<IUIObject>, CUIObjectPtr<IUIObject>, CUIObjectLess>::iterator pit = m_map.find(spValue);
				if ( pit != m_map.end() )
					m_map.erase(pit);
			}
			virtual	bool GetBeginIterator(IUIIterator** lppIterator)
			{
				if ( !lppIterator )
					return false;
				*lppIterator = NULL;
				if ( m_map.size() > 0 )
				{
					CUIMapIterator* p = new CUIMapIterator();
					if ( p )
					{
						assert(false);
						/*p->m_iterator = m_map.begin();
						p->AddRef();
						p->m_spMap = this;*/
						*lppIterator = p;
					}
					return true;
				}
				return false;
			}

		private:
			std::map<CUIObjectPtr<IUIObject>, CUIObjectPtr<IUIObject>, CUIObjectLess>	m_map;
		};
	}
}
